#include "xmppcore/stanzaerror.h"
#include "xmppcore/xmlwriter.h"
#include "xmppcore/constants.h"

namespace yoohoo_xmppcore {

const ProtocolKey StanzaError::PROTOCOL_KEY = ProtocolKey(XMPP_STRING_ERROR);
const ProtocolKey StanzaError::ERROR_DETAIL_PROTOCOL_KEY = ProtocolKey(XMPP_NAMESPACE_STANZA_ERROR);

StanzaError::StanzaError(StanzaErrorType stanzaErrorType, QString definedCondition, XmlLangText text) :
		_stanzaErrorType(stanzaErrorType) {
	_errorImpl = new StanzaError::StanzaErrorImpl(this);
	_errorImpl->setDefinedCondition(definedCondition);
	_errorImpl->setText(text);
	_d->type = XMPP_STRING_ERROR;
}

StanzaError::~StanzaError() {
	delete _errorImpl;
}

void StanzaError::setSenderXml(QString senderXml) {
	_senderXml = senderXml;
}

QString StanzaError::senderXml() {
	return _senderXml;
}

// stanza errors are recoverable(rfc3920 9.3)
bool StanzaError::shouldCloseStream() {
	return true;
}

void StanzaError::setApplicationSpecificCondition(XmppObject* applicationSpecificCondition) {
	_errorImpl->setApplicationSpecificCondition(applicationSpecificCondition);
}

XmppObject* StanzaError::applicationSpecificCondition() {
	return _errorImpl->applicationSpecificCondition();
}

void StanzaError::setDefinedCondition(QString definedCondition) {
	_errorImpl->setDefinedCondition(definedCondition);
}

QString StanzaError::definedCondition() {
	return _errorImpl->definedCondition();
}

void StanzaError::setText(XmlLangText text) {
	_errorImpl->setText(text);
}

XmlLangText StanzaError::text() {
	return _errorImpl->text();
}

void StanzaError::setStanzaKind(Stanza::StanzaKind stanzaKind) {
	_stanzaKind = stanzaKind;
}

Stanza::StanzaKind StanzaError::stanzaKind() const {
	return _stanzaKind;
}

void StanzaError::setStanzaErrorType(StanzaError::StanzaErrorType stanzaErrorType) {
	_stanzaErrorType = stanzaErrorType;
}

StanzaError::StanzaErrorType StanzaError::stanzaErrorType() {
	return _stanzaErrorType;
}

void StanzaError::setAttanchSenderXml(bool attachSenderXml) {
	_attachSenderXml = attachSenderXml;
}

bool StanzaError::attachSenderXml() {
	return _attachSenderXml;
}

XmppElement::ElementType StanzaError::elementType() const {
	return XmppElement::ElementTypeError;
}

Error::ErrorType StanzaError::errorType() const {
	return Error::ErrorTypeStanza;
}

StanzaError::StanzaErrorImpl::StanzaErrorImpl(StanzaError* stanzaError) : _stanzaError(stanzaError) {
}

bool StanzaError::StanzaErrorImpl::shouldCloseStream() {
	return false;
}

QString StanzaError::StanzaErrorImpl::definedConditionNamespace() {
	return XMPP_NAMESPACE_STANZA_ERROR;
}

void StanzaError::StanzaErrorImpl::writeErrorHeader(XmlWriter* writer) {
	writer->writeStartElement(XMPP_STRING_ERROR);
	StanzaError::StanzaErrorType stanzaErrorType = _stanzaError->stanzaErrorType();
	if (stanzaErrorType == StanzaError::StanzaErrorTypeCancel) {
		writer->writeAttribute("type", "cancel");
	} else if (stanzaErrorType == StanzaError::StanzaErrorTypeAuth) {
		writer->writeAttribute("type", "auth");
	} else if (stanzaErrorType == StanzaError::StanzaErrorTypeContinue) {
		writer->writeAttribute("type", "continue");
	} else if (stanzaErrorType == StanzaError::StanzaErrorTypeModify) {
		writer->writeAttribute("type", "modify");
	} else if (stanzaErrorType == StanzaError::StanzaErrorTypeWait) {
		writer->writeAttribute("type", "wait");
	}
}


void StanzaError::StanzaErrorImpl::writeErrorFooter(XmlWriter* writer) {
	writer->writeEndElement();
}

XmppElement::ElementType StanzaError::StanzaErrorImpl::elementType() const {
	return XmppElement::ElementTypeError;
}

Error::ErrorType StanzaError::StanzaErrorImpl::errorType() const {
	return Error::ErrorTypeStanza;
}

}
